Texture2D gTexture;

float PI = 3.1415926535;

SamplerState samLinear
{
    Filter = MIN_MAG_MIP_POINT;
    AddressU = Clamp;
    AddressV = Clamp;
};

/// Create Depth Stencil State (ENABLE DEPTH WRITING)
DepthStencilState NoDepth
{
	DepthEnable = TRUE;
};

/// Create Rasterizer State (Backface culling) 
RasterizerState BackCulling 
{ 
	CullMode = BACK; 
};

struct VS_INPUT_STRUCT
{
    float3 Pos : POSITION;
	float2 TexCoord : TEXCOORD0;

};
struct PS_INPUT_STRUCT
{
    float4 Pos : SV_POSITION;
	float2 TexCoord : TEXCOORD1;
};

PS_INPUT_STRUCT VS(VS_INPUT_STRUCT input)
{
	PS_INPUT_STRUCT output = (PS_INPUT_STRUCT)0;
	// Set the Position
	output.Pos = float4(input.Pos, 1.0f);
	// Set the Text coord
	output.TexCoord = input.TexCoord;
	return output;
}

float4 PS(PS_INPUT_STRUCT input):SV_TARGET
{
	float4 Color = gTexture.Sample( samLinear, input.TexCoord);
	
	float angle = 178.0;
	float angleHalf = 0.5 * angle * (PI / 180.0);
	float radius = sin(angleHalf);
  
	float2 uv = input.TexCoord;
	float2 xy = 2 * uv - 1;	//normalize
	float d = length(xy);
	if (d < (2 - radius))
	{
	  d = length(xy * radius);
	  float z = sqrt(1.0 - d * d);
	  float r = atan2(d, z) / PI;
	  float phi = atan2(xy.y, xy.x);
	  
	  uv.x = r * cos(phi) + 0.5f;
	  uv.y = r * sin(phi) + 0.5f;
	  Color = gTexture.Sample( samLinear, uv);
	}
	else
	{
	  uv = input.TexCoord;
	  Color = gTexture.Sample( samLinear, uv) * 0.5f;
	}

	return float4(Color.rgb,1);
}

technique11 FishEye
{
    pass P0
    {
		// Set states
		SetRasterizerState(BackCulling);
		SetDepthStencilState(NoDepth,0);
        SetVertexShader( CompileShader( vs_4_0, VS() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_4_0, PS() ) );
    }
}